package cn.wf.apigateway.filter;

import cn.wf.apigateway.exception.RateLimiterException;
import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVLET_DETECTION_FILTER_ORDER;

/**
 * @Description  限流，在鉴权之前，优先级最高
 * @Author 万飞
 * @Date 2018/8/19 1:30
 */
@Component
public class RateLimitFilter extends ZuulFilter {

    //令牌桶算法，一秒放100个(每秒往桶里放一百个令牌，超过丢掉，web请求过来获取一个令牌才能继续，否则拒绝)
    private static final RateLimiter RATE_LIMITER = RateLimiter.create(100);

    @Override
    public String filterType() {
        return PRE_TYPE;  //前置过滤器;
    }

    @Override
    public int filterOrder() {
        return SERVLET_DETECTION_FILTER_ORDER - 1; //SERVLET_DETECTION_FILTER_ORDER这个是优先级最高的，-1表示更高
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        if (!RATE_LIMITER.tryAcquire()) {  //RATE_LIMITER.tryAcquire()表示拿到一个令牌
            //如果没有拿到令牌，可以类似于tokenFilter设置响应不通过，返回没有拿到令牌的提示
            //也可以throw一个异常，下面使用这个方法
            throw new RateLimiterException();
        }

        return null;
    }
}
